package com.sinodata.bsm.center.web.action.resource;

import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.HashSet;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;

import net.sf.json.JSONArray;
import net.sf.json.JSONObject;

import com.sinodata.bsm.center.purview.FunctionConstants;
import com.sinodata.bsm.center.purview.UserFunctionValidate;
import com.sinodata.bsm.center.user.UserUtil;
import com.sinodata.bsm.center.web.action.resource.tree.AbstractTreeAction;
import com.sinodata.bsm.center.web.action.resource.tree.NodeCompare;
import com.sinodata.bsm.center.web.action.resource.tree.NodePrivilegeUtil;
import com.sinodata.bsm.center.web.action.resource.tree.TreeConstants;
import com.sinodata.bsm.common.vo.MonitorType;
import com.sinodata.bsm.common.vo.MotiResRel;
import com.sinodata.bsm.common.vo.Res;
import com.sinodata.bsm.common.vo.ResGroup;
import com.sinodata.bsm.common.vo.ResView;
import com.sinodata.bsm.common.vo.ResViewRel;

/**
 * 
 * <p>
 * Description: 全局资源的树
 * </p>
 *
 * @author wangyilin
 * @version 1.0

 * <p>
 * History: 
 *
 * Date                     Author         Version     Description
 * ---------------------------------------------------------------------------------
 * Jan 15, 2013 9:47:31 AM          wangyilin        1.0         To create
 * </p>
 *
 * @since 
 * @see
 */
public class ResSelectTreeAction extends AbstractTreeAction {
    @Override
    protected JSONArray children() throws Exception {

        JSONArray jsonArray = new JSONArray();
        Set<Long> relationTypeIds = resRelationService.getSelfAndSubRelationTypeIds();
        String[] idArray = this.id.split("[|]");
        if (idArray[0].equals("1")) {
            //初始化一视图下的顶级节点

            if (Long.parseLong(idArray[1]) == 2) {
                jsonArray = genMotiTypeView();
            } else if (Long.parseLong(idArray[1]) == 1) {
                jsonArray = genAppView();
            } else {
                jsonArray = genCommonResView(Long.parseLong(idArray[1]));
            }
        } else if (idArray[0].equals("4")) {
            try {
                long mtId = Long.parseLong(idArray[1]);
                List<ResGroup> groups = resGroupCache.findByMoitTypeId(mtId);
                Map<Long, List<ResGroup>> tmpMap = new HashMap<Long, List<ResGroup>>();
                List<ResGroup> rootResGroup = new ArrayList<ResGroup>();
                if (groups == null) {
                    groups = new ArrayList<ResGroup>(0);
                }
                for (ResGroup g : groups) {
                    if (g.getParentId() != null) {
                        List<ResGroup> arr = tmpMap.get(g.getParentId().longValue());
                        if (arr == null) {
                            arr = new ArrayList<ResGroup>();
                            tmpMap.put(g.getParentId().longValue(), arr);
                        }
                        arr.add(g);
                    } else {
                        rootResGroup.add(g);
                    }
                }
                Set<Long> includeList = new HashSet<Long>();
                for (ResGroup g : rootResGroup) {
                    JSONObject json = genResGroupNode(g, tmpMap, relationTypeIds, includeList, new ArrayList(0));
                    jsonArray.add(json);
                }
                Collection<Res> ress = resService.findAll();
                for (Res res : ress) {
                    Long mt = resTypeCache.getMoitTypeId(res.getResTypeId());
                    if (mt == null || mt.longValue() != mtId || includeList.contains(res.getId().longValue())) {
                        continue;
                    }
                    if (NodePrivilegeUtil.hasResViewPrivilege(res.getId(), relationTypeIds, request)) {
                        jsonArray.add(genResNode(res, 0L, relationTypeIds));
                    }
                }
            } catch (Exception e) {
                e.printStackTrace();
            }
        } else {
            //初始化某一节点

            JSONArray children = loadChildNode(Long.parseLong(idArray[1]), relationTypeIds);
            NodeCompare.sortChildNodeSequence(this.id, children);
            jsonArray = children;
        }
        return jsonArray;
    }

    private JSONObject genResGroupNode(ResGroup g, Map<Long, List<ResGroup>> childMap, Set<Long> relationTypesIds, Set<Long> includeList, List<String> traceList) {
        JSONObject json = new JSONObject();
        long pid = g.getParentId() == null ? 0 : g.getParentId();
        String nodeId = TreeConstants.NODE_TYPE_RESGROUP + "|" + g.getId() + "|" + pid;
        json.element("id", nodeId);
        if (traceList.contains(nodeId)) {
            json.element("open", true);
        }
        List<MotiResRel> relList = motiResRelCache.findByResGroupId(g.getId());
        JSONArray arr = new JSONArray();
        int num = 0;
        int maxStatus = 1;
        if (childMap.containsKey(g.getId().longValue())) {
            List<ResGroup> children = childMap.get(g.getId().longValue());
            for (ResGroup child : children) {
                JSONObject childJson = genResGroupNode(child, childMap, relationTypesIds, includeList, traceList);
                num += childJson.getInt("resNum");
                if (maxStatus < childJson.getInt("maxStatus")) {
                    maxStatus = childJson.getInt("maxStatus");
                }
                arr.add(childJson);
            }
        }
        if (relList != null) {
            for (MotiResRel rel : relList) {
                Res res = null;
                if ((res = resService.get(rel.getResId())) != null && NodePrivilegeUtil.hasResViewPrivilege(res.getId(), relationTypesIds, request)) {
                    JSONObject resjson = genResNode(res, 0L, relationTypesIds);
                    if (traceList.contains("2|" + res.getId() + "|0")) {
                        loadResNodeTrace(resjson, traceList, relationTypesIds);
                    }
                    arr.add(resjson);
                    includeList.add(res.getId().longValue());
                    if (maxStatus < res.getHealthStatus()) {
                        maxStatus = res.getHealthStatus();
                    }
                    num++;
                }
            }
        }

        json.element("maxStatus", maxStatus);
        json.element("iconSkin", "type" + maxStatus);
        json.element("resNum", num);
        if (num == 0) {
            json.element("name", g.getName());
        } else {
            json.element("name", g.getName() + " (" + num + ")");
        }
        NodePrivilegeUtil.getStatusCache(request, this.viewId).put(nodeId, new Integer[] { maxStatus, num });
        json.element("isParent", arr.size() > 0);
        json.element("children", arr);
        return json;
    }

    private static final Long APP_RESTYPE = 1105050000000L;

    private JSONArray genAppView() throws Exception {
        JSONArray jsonArray = new JSONArray();
        Set<Long> relationTypeIds = resRelationService.getSelfAndSubRelationTypeIds();
        List<Res> appList = resCache.getByResType(APP_RESTYPE);
        for (Res root : appList) {

            //                        if (!NodePrivilegeUtil.hasResViewPrivilege(root.getId(), relationTypeIds, request)) {
            //                continue;
            //            }
            JSONObject rootJson = genResNode(root, 0L, relationTypeIds);
            jsonArray.add(rootJson);
        }
        return jsonArray;
    }

    private JSONArray genMotiTypeView() {
        JSONArray jsonArray = new JSONArray();
        Set<Long> relationTypeIds = resRelationService.getSelfAndSubRelationTypeIds();
        try {

            List<MonitorType> mtList = resViewService.findAllMonitorType();
            Collection<Res> ress = resService.findAll();
            Set<Long> set = new HashSet<Long>();
            Map<Long, Integer[]> maxStatus = new HashMap<Long, Integer[]>();
            List<String> nodeTrace = NodePrivilegeUtil.findResNodeTrace(request, 0L);
            long mtTraceId = 0;
            if (nodeTrace.size() > 1) {
                String[] mtarr = nodeTrace.get(0).split("[|]");
                mtTraceId = Long.parseLong(mtarr[1]);
            }
            List<Res> traceResList = new ArrayList<Res>();
            for (Res res : ress) {
                Long mtval = resTypeCache.getMoitTypeId(res.getResTypeId());
                if (mtval == null) {
                    continue;
                }

                if (NodePrivilegeUtil.hasResViewPrivilege(res.getId(), relationTypeIds, request)) {
                    set.add(mtval);
                    if (maxStatus.containsKey(mtval)) {
                        if (maxStatus.get(mtval)[0] < res.getHealthStatus()) {
                            maxStatus.get(mtval)[0] = res.getHealthStatus();
                        }
                        maxStatus.get(mtval)[1] = maxStatus.get(mtval)[1] + 1;
                    } else {
                        maxStatus.put(mtval, new Integer[] { 1, res.getHealthStatus().intValue() });
                    }
                    if (mtTraceId == mtval) {
                        traceResList.add(res);
                    }
                }

            }
            for (MonitorType type : mtList) {
                JSONObject mtjson = genMonitorTypeNode(type, set);
                if (maxStatus.containsKey(type.getId().longValue())) {
                    Integer[] status = maxStatus.get(type.getId().longValue());
                    mtjson.element("name", type.getName() + " (" + status[1] + ")");
                    mtjson.element("iconSkin", "type" + status[0]);

                } else {
                    mtjson.element("name", type.getName());
                    mtjson.element("iconSkin", "type1");

                }
                jsonArray.add(mtjson);
            }

        } catch (Exception ex) {
            logger.error("error genernate base tree", ex);
        }
        return jsonArray;
    }

    private JSONArray genCommonResView(Long _viewId) {
        JSONArray jsonArray = new JSONArray();
        Set<Long> relationTypeIds = resRelationService.getSelfAndSubRelationTypeIds();
        Map<Long, List<ResGroup>> tmpMap = new LinkedHashMap<Long, List<ResGroup>>();
        List<ResGroup> groups = resGroupCache.findByResViewId(_viewId);
        List<ResGroup> rootResGroup = new ArrayList<ResGroup>();
        if (groups == null) {
            groups = new ArrayList<ResGroup>(0);
        }
        for (ResGroup g : groups) {
            if (g.getParentId() != null) {
                List<ResGroup> arr = tmpMap.get(g.getParentId().longValue());
                if (arr == null) {
                    arr = new ArrayList<ResGroup>();
                    tmpMap.put(g.getParentId().longValue(), arr);
                }
                arr.add(g);
            } else {
                rootResGroup.add(g);
            }
        }

        for (ResGroup g : rootResGroup) {
            JSONObject gjson = genResGroupNode2(g, tmpMap, relationTypeIds, new ArrayList<String>(0));
            jsonArray.add(gjson);
        }

        List<Long> rootList = new ArrayList<Long>();
        String userId = UserUtil.getInstance().getCurrentUserId();

        if (UserUtil.getInstance().isSysAdmin(userId)) {
            List<ResViewRel> viewRelList = resViewService.getResViewRelByViewId(_viewId);
            if (viewRelList != null) {
                for (ResViewRel rel : viewRelList) {
                    rootList.add(rel.getResId().longValue());
                }
            }
        } else {
            // 不是
            List<Long> resList = UserFunctionValidate.getResIdListForUser(FunctionConstants.VIEW_RES);
            rootList = resViewService.findChildByViewId(_viewId, resList);
        }
        Res res = null;

        for (Long rootId : rootList) {
            if ((res = resService.get(rootId)) != null) {
                JSONObject rootJson = genResNode(res, 0L, relationTypeIds);
                jsonArray.add(rootJson);
            }
        }
        return jsonArray;
    }

    @Override
    protected JSONArray root() throws Exception {
        JSONArray jsonArray = new JSONArray();
        ResView[] views = resViewService.findAll();
        List<ResView> purview = new ArrayList<ResView>();
        for (ResView view : views) {
            if (!UserFunctionValidate.viewFunctionValidate(view.getId(), FunctionConstants.VIEW_VIEW)) {
                continue;
            }
            purview.add(view);
            List<Long> resList = UserFunctionValidate.getResIdListForUser(FunctionConstants.VIEW_RES);
            if (resList == null || resList.size() == 0) {
                continue;
            }

        }
        for (ResView view : purview) {
            JSONObject viewNode = genResViewNode(view);
            jsonArray.add(viewNode);
        }

        return jsonArray;
    }

    private JSONObject genMonitorTypeNode(MonitorType mt, Set<Long> set) {
        JSONObject json = new JSONObject();
        String nodeId = TreeConstants.NODE_TYPE_MONITORTYPE + "|" + mt.getId() + "|0";
        json.element("id", nodeId);
        boolean isparent = set.contains(mt.getId()) || (resGroupCache.findByMoitTypeId(mt.getId()) != null);
        json.element("isParent", isparent);
        return json;
    }

}
